#include"mystdio.h"

void _fseek(_FILE*stream,int num,int f)
{
   lseek(stream->fileno,num,f);
}


_FILE* _fopen(const char* filename,const char* flag)
{
   assert(filename&&flag);//不能传空串
   
   int fd=0;
   int f=0;//打开方式
   if(strcmp(flag,"r")==0)//读
   {
       f=O_RDONLY;//系统级打开的参数
       fd=open(filename,f,0666);
   }
   else if(strcmp(flag,"r+")==0)//读写
   {
       f=(O_RDONLY|O_WRONLY);
       fd=open(filename,f,0666);
   }

   else if(strcmp(flag,"w")==0)//两者相等返回0
   {
      f= (O_CREAT|O_WRONLY|O_TRUNC);
      fd=open(filename,f,0666);
   }
   else if(strcmp(flag,"w+")==0)//读写
   {
     //printf("w+\n");
     f=(O_RDWR | O_CREAT | O_TRUNC);
     fd=open(filename,f,0666);
   }

   else if(strcmp(flag,"a")==0)//追加写
   {
     f=(O_CREAT|O_WRONLY|O_APPEND);
     fd=open(filename,f,0666);
   }
   else if(strcmp(flag,"a+")==0)//追加读写
   {
   f=(O_CREAT|O_WRONLY|O_APPEND|O_RDONLY);                                                                         
   fd=open(filename,f,0666);  
   }

   else if(strcmp(flag,"r")==0)//只读
   {
     f=O_RDONLY;
     fd=open(filename,f);
   }
   else return NULL;

  if(fd==-1) return NULL;

  _FILE* fdd=(_FILE*)malloc(sizeof(_FILE));
  
  if(!fdd)//创建失败
  {
    perror("eror:\n");
    exit(-1);
  }

  memset(fdd, 0, sizeof(_FILE));//初始化用户及缓冲区
  fdd->fileno=fd; 
  //printf("fdd->fileno: %d\n", fdd->fileno)
  fdd->_flush=flush_line;
  fdd->out_pos=0;
  //printf("fdd->fileno: %d\n", fdd->fileno);
  return fdd ;
}

int _fwrite(_FILE*fp,const char* s,int len)
{
    memcpy(&fp->outbuffer[fp->out_pos],s,len);//先写到用户及缓冲区，再看刷新方式

    fp->out_pos+=len;
    
    if(fp->_flush==flush_no)//不缓存
    {
      write(fp->fileno,fp->outbuffer,fp->out_pos);
      fp->out_pos=0;
    }
    else if(fp->_flush==flush_line)//行缓存 abcd\n  5 
    {
        if(s[len-1]=='\n')
        {

         // printf("行\n");
          write(fp->fileno,fp->outbuffer,fp->out_pos);
          fp->out_pos=0;
        }
    }
    else{//全缓冲，满了才刷到文件中
        if(fp->out_pos==SIZE)
        {
          write(fp->fileno,fp->outbuffer,fp->out_pos);
          fp->out_pos=0;
        }
    } 

    return len;
}

void _fclose(_FILE* fp)
{
   assert(fp);
   
   if(fp->out_pos>0) _fflush(fp);//关闭之前先看用户及缓冲区

   close(fp->fileno); 
   free(fp);
}

void _fflush(_FILE* fp)//可以刷新内核级缓冲区
{
   if(fp->out_pos>0)
   {
     write(fp->fileno,fp->outbuffer,fp->out_pos);//刷新就是写入
     fp->out_pos=0;
     //lseek(fp->fileno, 0, SEEK_SET);
   }
}

size_t _fread(void*ptr,size_t size,size_t num, _FILE*stream)
{
   if(stream->out_pos>0) _fflush(stream);
    
   size_t readsize= size*num;//ptr的大小
   size_t buffersize=SIZE;//缓冲区的大小
   size_t total=0;

   if(buffersize>=readsize)
   { 
     ssize_t ret=read(stream->fileno,stream->inbuffer,readsize);
     
     if(ret<0)  
     {
       printf("不对\n");
       perror("ret\n");
     }
     
     memcpy(ptr,stream->inbuffer,ret);
     *((char*)ptr+ret)='\0';
     total=ret;

     //printf("%s\n",ptr);
   }
   else
   {
     while(total<readsize)
     {
       size_t ret=read(stream->fileno,stream->inbuffer,buffersize);
       if(ret<0) break;

       memcpy((char*)ptr+total,stream->inbuffer,ret);
       total+=ret;

       *((char*)ptr+total)='\0';
     } 
   }
  return total;
}
